/*
  Labotronik EthernetWifi Switch
  Copyright (C) 2012 Marc Chapdelaine

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef TFTPCLIENT_HPP
#define TFTPCLIENT_HPP

#include <QWidget>
#include <QDialog>

class QUdpSocket;
class QString;
class QTimer;
class QByteArray;
class QFile;
class QDataStream;
class QStatusBar;
class QVBoxLayout;

namespace Tftp {

	enum Opcode {
		UNKONWNOPCODE = 0,
		READREQUEST = 1,
		WRITEREQUEST = 2,
		DATA = 3,
		ACK = 4,
		ERROR = 5
	};
	
	enum Modes {
		UNKNOWNMODE = 0,
		NETASCII = 1,
		OCTET = 2,
		MAIL = 3
	};
	
	enum ConnectionState {
		INITSTATE,
		CONNECTIONINITSTATE,
		READYSENDFILESTATE,
		DATASENTSTATE,
		WAITINGDATAACKSTATE,
		LASTDATAPACKETACKSTATE
	};
	
	class TftpClient : public QDialog {
	Q_OBJECT
	
	public:
		TftpClient(const QString& serverAddress_, quint16 port_ = 69, QWidget* parent = NULL);
		~TftpClient();
		
		bool put(const QString& remoteFileName, const QString& localFileName);
		bool get(const QString& remoteFileName, const QString& localFileName);
	
		inline unsigned short getPort() const {return port;}
		
	private slots:
		void operationTimeout();
		void readDatagram();
	
	private:
		bool sendRequestPacket(Opcode code, const QString& remoteFileName);
		bool sendDataPacket(bool increment);
		
		static Opcode getOpcodeFromPacket(const QByteArray& packet);
		static bool isAck(const QByteArray& packet, quint16& blockNumber);
		static unsigned short generateTid();
		
		static void displayQByteArrayData(const QByteArray& data, unsigned int maxDisplay = 512);
	
		quint16 port;
		quint16 serverTid;
		quint16 currentblockId;
		int readBufferSize;
		static quint16 tidSeed;
		ConnectionState currentState;
		
		QString* serverAddress;
		QUdpSocket* socket;
		QTimer* operationTimer;
		QFile* file;
		QDataStream* fileData;
		char* readBuffer;
		QStatusBar* statusBar;
		QVBoxLayout* mainLayout;
	};


}


#endif //TFTPCLIENT_HPP